home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / appletalk / uab.shar / uab.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-12  |  20.4 KB  |  920 lines

  1. static char rcsid[] = "$Author: cck $ $Date: 88/10/10 18:21:31 $";
  2. static char rcsident[] = "$Header: /src/local/mac/cap/etalk/RCS/uab.c,v 1.32 88/10/10 18:21:31 cck Rel $";
  3. static char revision[] = "$Revision: 1.32 $";
  4.  
  5. /*
  6.  * UAB - Unix AppleTalk Bridge
  7.  *
  8.  *  AppleTalk Bridge For Unix
  9.  *
  10.  *  written by Charlie C. Kim
  11.  *     Academic Computing and Communications Group
  12.  *     Center For Computing Activities
  13.  *     Columbia University
  14.  *   August 1988
  15.  *
  16.  *
  17.  * Copyright (c) 1988 by The Trustees of Columbia University 
  18.  *  in the City of New York.
  19.  *
  20.  * Permission is granted to any individual or institution to use,
  21.  * copy, or redistribute this software so long as it is not sold for
  22.  * profit, provided that this notice and the original copyright
  23.  * notices are retained.  Columbia University nor the author make no
  24.  * representations about the suitability of this software for any
  25.  * purpose.  It is provided "as is" without express or implied
  26.  * warranty.
  27.  *
  28.  * Edit History:
  29.  *
  30.  *  April 3, 1988  CCKim Created
  31.  *
  32. */
  33.  
  34. static char columbia_copyright[] = "Copyright (c) 1988 by The Trustees of \
  35. Columbia University in the City of New York";
  36.  
  37. #include <stdio.h>
  38. #include <ctype.h>
  39. #include <signal.h>
  40. #include <sys/param.h>
  41. #ifndef _TYPES
  42. # include <sys/types.h>
  43. #endif
  44. #include <sys/socket.h>
  45. #include <sys/ioctl.h>
  46. #include <sys/uio.h>
  47. #include <sys/time.h>
  48. #include <net/if.h>
  49. #include <netinet/in.h>
  50.  
  51. #include <netat/appletalk.h>
  52. #include <netat/compat.h>
  53. #include "mpxddp.h"
  54. #include "gw.h"
  55. #include "if_desc.h"
  56. #include "log.h"
  57.  
  58. /* bridge description file */
  59. #ifndef BRIDGE_DESC
  60. # define BRIDGE_DESC "bridge_desc"
  61. #endif
  62. private char *bd_file = BRIDGE_DESC; /* default bridge description */
  63.  
  64. private int debug = 0;
  65. private int have_log = 0;
  66.  
  67. /* import  link access protocol descriptions */
  68. /* ethertalk */
  69. extern struct lap_description ethertalk_lap_description;
  70.  
  71. /* IMPORT: multiplex ddp descriptions */
  72. /* import mpx ddp module udpcap */
  73. extern struct mpxddp_module mkip_mpx; /* modified kip udp port range */
  74. extern struct mpxddp_module kip_mpx; /* no rebroadcaster allowed, */
  75.                      /* rewrites atalk.local */
  76.  
  77. private void disassociate();
  78. private int mark();        /* mark alive */
  79. private void usage();
  80. private char *doargs();
  81. export void dumpether();
  82.  
  83. /* these are currently only used internally */
  84. export boolean match_string();
  85. export char *gettoken();
  86. export char *getdelimitedstring();
  87. export char *mgets();
  88.  
  89. /* guts of start */
  90. private boolean parse_bd();
  91. private void pbd_err();
  92. private int parse_net();
  93.  
  94. private boolean connect_port();
  95.  
  96. /* control module */
  97. private void setup_signals();    /* MODULE:CONTROL */
  98. private void listsigactions();    /* MODULE:CONTROL */
  99. private int handlesigaction();    /* MODULE:CONTROL */
  100. private int runsignalactions();    /* MODULE:CONTROL */
  101. private void set_uab_pid();    /* MODULE:CONTROL */
  102. private int get_uab_pid();    /* MODULE:CONTROL */
  103.  
  104. /*
  105.  * give away terminal
  106.  *
  107. */
  108. private void
  109. disassociate()
  110. {
  111.   int i;
  112.   /* disassociate */
  113.   if (fork())
  114.     _exit(0);            /* kill parent */
  115.   for (i=0; i < 3; i++) close(i); /* kill */
  116.   (void)open("/",0);
  117. #ifdef NODUP2
  118.   (void)dup(0);            /* slot 1 */
  119.   (void)dup(0);            /* slot 2 */
  120. #else
  121.   (void)dup2(0,1);
  122.   (void)dup2(0,2);
  123. #endif
  124. #ifdef TIOCNOTTY
  125.   if ((i = open("/dev/tty",2)) > 0) {
  126.     (void)ioctl(i, TIOCNOTTY, (caddr_t)0);
  127.     (void)close(i);
  128.   }
  129. #endif
  130. }
  131.  
  132. private void
  133. usage()
  134. {
  135.   fprintf(stderr,"Usage: uab -D <debug level> -f <bridge description file>\n");
  136.   listsigactions();
  137.   exit(1);
  138. }
  139.  
  140. private char *
  141. doargs(argc, argv)
  142. int argc;
  143. char **argv;
  144. {
  145.   int c, pid;
  146.   extern char *optarg;
  147.   extern int optind;
  148.  
  149.   while ((c = getopt(argc, argv, "D:df:l:")) != EOF) {
  150.     switch (c) {
  151.     case 'f':
  152.       bd_file = optarg;
  153.       break;
  154.     case 'D':
  155.       debug = atoi(optarg);
  156.       break;
  157.     case 'd':
  158.       debug++;
  159.       break;
  160.     case 'l':
  161.       have_log = 1;
  162.       logfileis(optarg, "w");
  163.       break;
  164.     }
  165.   }
  166.  
  167.   if (optind == argc)
  168.     return;
  169.   
  170.   if ((pid = get_uab_pid()) < 0) 
  171.     log(L_EXIT|LOG_LOG,
  172.     "Couldn't get Unix AppleTalk Bridge pid, is it running?");
  173.  
  174.   for (; optind < argc ; optind++)
  175.     if (handlesigaction(argv[optind], pid) < 0)
  176.       usage();
  177.   exit(0);
  178. }
  179.  
  180. main(argc, argv)
  181. char **argv;
  182. int argc;
  183. {
  184.   int mark();
  185.  
  186.   doargs(argc, argv);
  187.   set_debug_level(debug);
  188.   if (!debug) {
  189.     disassociate();
  190.     if (!have_log)
  191.       nologfile();        /* clear stderr as log file */
  192.   }
  193.   setup_signals();
  194.   ddp_route_init();        /* initialize */
  195.   if (!parse_bd(bd_file))
  196.     exit(1);
  197.  
  198.   ddp_route_start();
  199.   set_uab_pid();        /* remember */
  200.   /* mark every 30 minutes */
  201.   Timeout(mark, (caddr_t)0, sectotick(60*30));
  202.   do {
  203.     abSleep(sectotick(30), TRUE);
  204.   } while (runsignalactions());
  205. }
  206.  
  207. private int
  208. mark()
  209. {
  210.   log(LOG_LOG, "uab running");
  211. }
  212.  
  213. export void
  214. dumpether(lvl,msg, ea)
  215. int lvl;
  216. char *msg;
  217. byte *ea;
  218. {
  219.   log(lvl, "%s: %x %x %x %x %x %x",msg,
  220.      ea[0], ea[1], ea[2],
  221.      ea[3], ea[4], ea[5]);
  222. }
  223.  
  224. /*
  225.  * start of guts
  226.  *   parse the file
  227.  *
  228. */
  229.  
  230. /* list of known allowable lap descriptions */
  231. private struct lap_description *ld_list[] = {
  232.   ðertalk_lap_description,
  233.   NULL
  234. };
  235.  
  236. /* list of valid interfaces */
  237. private struct interface_description *id_list;
  238.  
  239. private struct mpxddp_module *mdm_list[] = {
  240.   &kip_mpx,
  241.   &mkip_mpx,
  242.   NULL
  243. };
  244.  
  245. private struct mpxddp_module *check_local_delivery();
  246. private struct lap_description *check_lap_type();
  247.  
  248. /*
  249.  * check out local delivery methods (couldn't get the pointers right,
  250.  * so just hard coded the names :-)
  251.  *
  252. */
  253. private struct mpxddp_module *
  254. check_local_delivery(local, invalid)
  255. char *local;
  256. int *invalid;
  257. {
  258.   struct mpxddp_module **m;
  259.  
  260.   *invalid = FALSE;
  261.   if (strcmpci(local, "none") == 0)
  262.     return(NULL);
  263.   
  264.   for (m = mdm_list; *m ; m++) {
  265.     if (strcmpci((*m)->mpx_key, local) == 0)
  266.       return(*m);
  267.   }
  268.   *invalid = TRUE;
  269.   return(NULL);
  270. }
  271.  
  272. /*
  273.  * check for a valid lap type
  274.  *
  275. */
  276. private struct lap_description *
  277. check_lap_type(name)
  278. char *name;
  279. {
  280.   struct lap_description **ld;
  281.   char **keys;
  282.  
  283.   for (ld = ld_list; *ld ; ld++) {
  284.     for (keys = (*ld)->ld_key; *keys; keys++)
  285.       if (strcmpci(*keys, name) == 0)
  286.     return(*ld);
  287.   }
  288.   return(NULL);
  289. }
  290.  
  291. private void
  292. interface_dump_table(fd)
  293. FILE *fd;
  294. {
  295.   IDESC_TYPE *id = id_list;
  296.  
  297.   while (id) {
  298.     if (id->id_ld && id->id_ld->ld_dump_routine)
  299.       (*id->id_ld->ld_dump_routine)(fd, id);
  300.     id = id->id_next;        /* move to next in our list */
  301.   }
  302. }
  303.  
  304. private void
  305. interface_dump_stats(fd)
  306. FILE *fd;
  307. {
  308.   IDESC_TYPE *id = id_list;
  309.  
  310.   while (id) {
  311.     if (id->id_ld && id->id_ld->ld_dump_routine)
  312.       (*id->id_ld->ld_stats_routine)(fd, id);
  313.     id = id->id_next;        /* move to next in our list */
  314.   }
  315. }
  316.  
  317. /*
  318.  * match base against pattern
  319.  * special chars are
  320.  * allow: % to match any char
  321.  *        * (at start) to match anything (anything following * is ignored)
  322.  *        * at end to match previous then anything
  323.  *
  324. */
  325. export boolean
  326. match_string(base, pattern)
  327. char *base;
  328. char *pattern;
  329. {
  330.   char pc, bc;
  331.  
  332.   while ((pc = *pattern++)) {
  333.     if ((bc = *base) == '\0')
  334.       return(FALSE);
  335.     switch (pc) {
  336.     case '%':
  337.       break;
  338.     case '*':
  339.       return(TRUE);
  340.     default:
  341.       if (bc != pc)
  342.     return(FALSE);
  343.       break;
  344.     }
  345.     base++;
  346.   }
  347.   if (*base != '\0')        /* end of string */
  348.     return(FALSE);        /* no, and pattern has ended! */
  349.   return(TRUE);
  350. }
  351.  
  352. /*
  353.  * get a token.
  354.  *  returns a pointer to a copy of the token (must be saved if you
  355.  *  wish to keep across invocations of gettoken).
  356.  *
  357.  * We depend upon isspace to define white space (should be space, tab,
  358.  * carriage return, line feed and form feed
  359.  *
  360.  * "/" may be used to quote the characters.
  361.  *
  362.  * "#" at the start of a line (possibly with white space in front)
  363.  * is consider a comment.
  364.  *
  365. */
  366. private char tmpbuf[BUFSIZ];    /* temp for gettoken and getdel...string */
  367. #define TMPBUFENDP (tmpbuf+BUFSIZ-2) /* room for null */
  368. char *
  369. gettoken(pp)
  370. char **pp;
  371. {
  372.   char *p = *pp;
  373.   char *dp = tmpbuf;
  374.   char c;
  375.   boolean sawquote;
  376.  
  377.   /* no string or at the end */
  378.   if (p == NULL || (c = *p) == '\0')
  379.     return(NULL);
  380.  
  381.   while ((c = *p) && isascii(c) && isspace(c)) /* skip over any spaces */
  382.     p++;
  383.  
  384.   if (*p == '#') {        /* is a comment */
  385.     *pp = p;            /* repoint */
  386.     return(NULL);
  387.   }
  388.  
  389.   for (sawquote=FALSE, c = *p ; c != '\0' && dp < TMPBUFENDP; c = *p) {
  390.     if (sawquote) {        /* in quote mode? */
  391.       *dp++ = c;        /* yes, move char in */
  392.       sawquote = FALSE;        /* and turn off quote mode */
  393.     } else if (c == '\\')    /* else, is the char a quote? */
  394.       sawquote = TRUE;        /* yes, turn quote flag on */
  395.     else if (isascii(c) && isspace(c)) /* or is it a space? */
  396.       break;            /* yes, so stop tokenizing */
  397.     else *dp++ = c;        /* wasn't in quote, wasn't a quote */
  398.                 /* char and wasn't a space, so part of */
  399.                 /* token */
  400.     p++;            /* move past char */
  401.   }
  402.   *dp = '\0';            /* tie off string */
  403.   *pp = p;            /* update pointer */
  404.   if (tmpbuf == dp)        /* nothing in string? */
  405.     return(NULL);
  406.   return(tmpbuf);            /* return pointer to token */
  407. }
  408.  
  409. /*
  410.  * get a string deliminted by the characters start and end
  411.  *
  412. */
  413. export char *
  414. getdelimited_string(pp, start, end)
  415. char **pp;
  416. char start;
  417. char end;
  418. {
  419.   char *p = *pp;
  420.   char *dp = tmpbuf;
  421.   char c;
  422.   boolean sawquote;
  423.  
  424.   if (start)
  425.     while ((c = *p) && c != start) /* skip to start */
  426.       p++;
  427.   *pp = p;
  428.   if (c == '\0')
  429.     return(NULL);
  430.   p++;                /* skip begin char */
  431.   for (sawquote=FALSE,c = *p; c != '\0' || dp < TMPBUFENDP; c = *p) {
  432.     if (sawquote) {        /* in quote mode? */
  433.       *dp++ = c;        /* yes, move char in */
  434.       sawquote = FALSE;        /* and turn off quote mode */
  435.     } else if (c == '\\')    /* else, is the char a quote? */
  436.       sawquote = TRUE;        /* yes, turn quote flag on */
  437.     else if (c == end) {    /* or is it our end char */
  438.       p++;            /* yes, push past char */
  439.       break;            /* and stop tokenizing */
  440.     }
  441.     else *dp++ = c;        /* wasn't in quote, wasn't a quote */
  442.                 /* char and wasn't a end char, so part */
  443.                 /* of token */
  444.     p++;            /* move past char */
  445.   }
  446.   *dp = '\0';            /* tie off string */
  447.   *pp = p;            /* update pointer */
  448.   if (tmpbuf == dp)        /* nothing in string? */
  449.     return(NULL);
  450.   return(tmpbuf);            /* return pointer to token */
  451. }
  452.  
  453.  
  454. /*
  455.  * like gets, but accepts fd, will always null terminate,
  456.  * accepts "\" at the end of a line as a line continuation.
  457.  *
  458. */
  459. export char *
  460. mgets(buf, size, fd)
  461. char *buf;
  462. int size;
  463. FILE *fd;
  464. {
  465.   int c;
  466.   char lc = 0;
  467.   char *p = buf;
  468.  
  469.   if (size)            /* make room for the null */
  470.     size--;
  471.   while ((c = getc(fd)) != EOF && size) {
  472.     if (c == '\n' || c == '\r') {
  473.       if (lc == '\\') {
  474.     p--;            /* backup pointer (toss the "\" */
  475.     lc = 0;            /* and clear lc */
  476.     continue;
  477.       }
  478.       break;
  479.     }
  480.     *p++ = c;
  481.     size--;
  482.     lc = c;
  483.   }
  484.   *p = '\0';            /* tie off string */
  485.   return(c == EOF ? NULL : buf);
  486. }
  487.  
  488.  
  489. /*
  490.  * parse a bridge description file
  491.  *
  492. */
  493. private boolean
  494. parse_bd(file)
  495. char *file;
  496. {
  497.   FILE *fd;
  498.   char hostname[BUFSIZ];    /* room for host name */
  499.   char buf[BUFSIZ];        /* room for a lot */
  500.   char *p, *bp, *t;
  501.   char *savedpat = NULL;
  502.   int i;
  503.   int lineno = 0;        /* start line numbers */
  504.   int connected_ports = 0;
  505.   int anymatches = TRUE;
  506.   LDESC_TYPE *ld;
  507.   IDESC_TYPE *id;
  508.   
  509.   if ((id = (IDESC_TYPE *)malloc(sizeof(IDESC_TYPE))) == NULL)
  510.     log(L_EXIT|L_UERR|LOG_LOG, "out of memory in parse_pd");
  511.  
  512.   if (gethostname(hostname, sizeof(hostname)) < 0) {
  513.     log(L_UERR|LOG_LOG, "Can't get hostname: will only accept wildcards");
  514.     hostname[0] = '\0';
  515.   }
  516.  
  517.   if ((fd = fopen(file, "r")) == NULL)
  518.     log(L_EXIT|L_UERR|LOG_LOG, "Can't open file %s", file);
  519.  
  520.   while (mgets(buf, sizeof(buf),fd)) {
  521.     lineno++;
  522.     p = buf;
  523.     /* get the tokens */
  524.     if ((bp = gettoken(&p)) == NULL) /* comment or blank */
  525.       continue;
  526.     if (savedpat && strcmp(bp, savedpat) == 0);
  527.     if (!savedpat) {
  528.       /* no saved pattern */
  529.       if (!match_string(hostname, bp)) /* none of our concern */
  530.     continue;
  531.       savedpat = (char *)strdup(bp);    /* save the pattern */
  532.     } else {
  533.       /* saved pattern */
  534.       if (savedpat && strcmp(bp, savedpat) != 0)
  535.     continue;
  536.     }
  537.     log(LOG_PRIMARY, "Port description match on %s", bp);
  538.     anymatches = TRUE;
  539.     if ((bp = getdelimited_string(&p, '[', ']')) == NULL) {
  540.       pbd_err(lineno, buf, "missing lap specification");
  541.       continue;
  542.     }
  543.     if ((t = (char *)index(bp, ','))) {
  544.       *t = '\0';        /* divide */
  545.       t++;            /* and conquer*/
  546.     }
  547.     if ((ld = check_lap_type(bp)) == NULL) {
  548.       pbd_err(lineno,buf, "invalid lap type");
  549.       continue;
  550.     }
  551.     id->id_ld = ld;        /* remember for later */
  552.     id->id_intf = NULL;
  553.     id->id_intfno = 0;
  554.     bp = t;            /* move to device dependent */
  555.     if (bp) {
  556.       if ((t = (char *)index(bp, ':'))) {
  557.     id->id_intfno = atoi(t+1);    /* convert to int */
  558.     if (id->id_intfno == 0 && t[1] != '0') {
  559.       pbd_err(lineno,buf,
  560.           "interface specification, expected number after colon");
  561.       continue;
  562.     }
  563.     *t = '\0';        /* kill of interface # */
  564.       }
  565.       id->id_intf = (char *)strdup(bp); /* copy interface name */
  566.     } else {
  567.       if (ld->ld_wants_data) {
  568.     pbd_err(lineno, buf, "this lap type requires additional data");
  569.     continue;
  570.       }
  571.     }
  572.     if ((bp = gettoken(&p)) == NULL) {
  573.       pbd_err(lineno, buf, "missing local delivery");
  574.       if (id->id_intf)
  575.     free(id->id_intf);
  576.       continue;
  577.     }
  578.     id->id_local = check_local_delivery(bp, &i);
  579.     if (i) {
  580.       pbd_err(lineno, buf, "invalid local delivery");
  581.       if (id->id_intf)
  582.     free(id->id_intf);
  583.       continue;
  584.     }
  585.     id->id_zone = NULL;
  586.     if ((bp = getdelimited_string(&p, '[', ']')) != NULL) {
  587.       byte *z;
  588.  
  589.       id->id_isabridge = TRUE;
  590.       id->id_network = parse_net(bp, NULL);    /* get network number */
  591.       z = (byte *)index(bp, ',');
  592.       if (z) {
  593.     z = (byte *)strdup(z);    /* duplicate string */
  594.     *z = strlen(z+1);    /* make pstr */
  595.     id->id_zone = z;
  596.       } else id->id_zone = NULL;
  597.       id->id_zone = z ? ((byte *)strdup(z)) : NULL;
  598.     } else id->id_isabridge = FALSE;
  599.     log(LOG_PRIMARY, "interface %s%d", id->id_intf, id->id_intfno);
  600.     if (id->id_local)
  601.       log(LOG_PRIMARY, "\tlocal delivery is %s", id->id_local->mpx_name);
  602.     else
  603.       log(LOG_PRIMARY, "\tno local delivery");
  604.     if (id->id_isabridge) {
  605.       if (id->id_network)
  606.     log(LOG_PRIMARY, "\tnetwork %d.%d", nkipnetnumber(id->id_network),
  607.            nkipsubnetnumber(id->id_network));
  608.       else
  609.     log(LOG_PRIMARY, "\tnetwork number from network");
  610.       if (id->id_zone)
  611.     log(LOG_PRIMARY, "\tzone %d-'%s'", *id->id_zone, id->id_zone+1);
  612.     } else
  613.       log(LOG_PRIMARY, "\tnot routing on this interface");
  614.     if ((*ld->ld_init_routine)(id, TRUE)) {
  615.       connected_ports++;
  616.       id->id_next = id_list;    /* link into list */
  617.       id_list = id;        /* of active ld descriptions */
  618.       /* create a new id */
  619.       if ((id = (IDESC_TYPE *)malloc(sizeof(IDESC_TYPE))) == NULL)
  620.     log(L_EXIT|L_UERR|LOG_LOG, "out of memory in parse_pd");
  621.     } else {
  622.       log(LOG_PRIMARY, "Couldn't establish the port");
  623.     }
  624.     if (id->id_intf)
  625.       free(id->id_intf);
  626.     if (id->id_zone)
  627.       free(id->id_zone);
  628.   }
  629.   if (id)
  630.     free(id);
  631.   if (savedpat)
  632.     free(savedpat);
  633.   fclose(fd);
  634.   if (connected_ports == 0) {
  635.     log(LOG_PRIMARY, "NO CONNECTED PORTS, ABORTING");
  636.     return(FALSE);
  637.   }
  638.   return(TRUE);
  639. }
  640.  
  641. private void
  642. pbd_err(lineno, line, msg)
  643. {
  644.   log(LOG_LOG, "error in line %d - %s",lineno, msg);
  645.   log(LOG_LOG, "line: %s", line);
  646. }
  647.  
  648. /*
  649.  * parse a network number in the format:
  650.  *  number
  651.  *  number.number (means high byte, low byte)
  652.  * where the number can be hex (0x or 0X preceeding) or octal (leading 0) 
  653.  *  (handled by strtol)
  654.  *
  655.  * set *rptr to point to last part of "s" used
  656.  *
  657. */
  658. private int
  659. parse_net(s, rptr)
  660. char *s;
  661. char **rptr;
  662. {
  663.   char *e;
  664.   int p1, p2;
  665.   
  666.   p1 = strtol(s, &e, 0);    /* convert */
  667.   if (rptr)
  668.     *rptr = e;
  669.   if (*e != '.')
  670.     return(htons(p1));
  671.   p2 = strtol(e+1, rptr, 0);
  672.   return(htons( ((p1&0xff) << 8) | (p2&0xff)));
  673. }
  674.  
  675.  
  676. /* MODULE: CONTROL */
  677.  
  678. /* pid file */
  679. #ifndef UAB_PIDFILE
  680. # define UAB_PIDFILE "/etc/uab.pid"
  681. #endif
  682.  
  683. /* logging file */
  684. #ifndef UAB_RUNFILE
  685. # define UAB_RUNFILE "/usr/tmp/uab.run"
  686. #endif
  687.  
  688. #ifndef UAB_STATSFILE
  689. # define UAB_STATSFILE "/usr/tmp/uab.stats"
  690. #endif
  691.  
  692. #ifndef UAB_DUMPFILE
  693. # define UAB_DUMPFILE "/usr/tmp/uab.dump"
  694. #endif
  695.  
  696. private char *uab_runfile = NULL;
  697. private char *uab_pidfile = UAB_PIDFILE;
  698. private char *uab_statsfile = UAB_STATSFILE;
  699. private char *uab_dumpfile = UAB_DUMPFILE;
  700.  
  701. private int uab_end();
  702. private int uab_undebug();
  703. private int uab_debuginc();
  704. private int table_dump();
  705. private int stats_dump();
  706.  
  707. /*
  708.  * do nice stuff
  709.  *
  710. */
  711.  
  712. private void
  713. set_uab_pid()
  714. {
  715.   FILE *fd;
  716.  
  717.   if ((fd = fopen(uab_pidfile, "w")) != NULL) {
  718.     fprintf(fd, "%d\n",getpid());
  719.     fclose(fd);
  720.   }
  721. }
  722.  
  723. private
  724. get_uab_pid()
  725. {
  726.   FILE *fp;
  727.   int pid;
  728.  
  729.   if ((fp = fopen(uab_pidfile, "r")) == NULL) {
  730.     log(L_UERR|LOG_LOG, "No pid file - maybe the daemon wasn't running?");
  731.     return(-1);
  732.   }
  733.   if (fscanf(fp, "%d\n", &pid) != 1) {
  734.     log(LOG_LOG, "pid file was bad");
  735.     return(-1);
  736.   }
  737.   return(pid);
  738. }
  739.  
  740.  
  741. #define NSIGACT 6
  742.  
  743. struct sigtab {
  744.   char *s_name;
  745.   int s_signal;
  746.   char *s_action;
  747. };
  748.  
  749. private struct sigtab sigtab[NSIGACT] = {
  750. #define SIG_TDUMP SIGUSR1
  751.   "tdump", SIG_TDUMP, "dump tables",
  752. #define SIG_DEBUG SIGIOT
  753.   "debug", SIG_DEBUG, "increment debug level",
  754. #define SIG_NODEBUG SIGEMT
  755.   "nodebug", SIG_NODEBUG, "clear debugging",
  756. #define SIG_STAT SIGUSR2
  757.   "statistics", SIG_STAT, "dump statistics",
  758.   "stat", SIG_STAT, "dump statistics",
  759. #define SIG_EXIT SIGTERM
  760.   "exit", SIG_EXIT, "stop running uab"
  761. };
  762.  
  763. private int signalactions; /* no signal actions to handle */
  764. #define SA_TABLE_DUMP 0x1
  765. #define SA_STATISTICS 0x2
  766. #define SA_UNDEBUG 0x4        /* turn off debugging */
  767. #define SA_DEBUG 0x8        /* turn on debugging */
  768. private void
  769. setup_signals()
  770. {
  771.   signal(SIG_STAT, stats_dump);
  772.   signal(SIG_TDUMP, table_dump);
  773.   signal(SIG_EXIT, uab_end);
  774.   signal(SIG_DEBUG, uab_debuginc);
  775.   signal(SIG_NODEBUG, uab_undebug);
  776.   signalactions = 0; /* no signal actions to handle */
  777. }
  778.  
  779. private void
  780. listsigactions()
  781. {
  782.   int i;
  783.   struct sigtab *st;
  784.  
  785.   fprintf(stderr, " commands:\n");
  786.   for (st = sigtab, i = 0; i < NSIGACT; i++, st++)
  787.     fprintf(stderr,"\t%s\t%s\n", st->s_name, st->s_action);
  788. }
  789.  
  790. private int
  791. handlesigaction(s, pid)
  792. char *s;
  793. {
  794.   int i;
  795.   struct sigtab *st;
  796.  
  797.   for (st = sigtab, i = 0; i < NSIGACT; i++, st++) {
  798.     if (strcmpci(s, st->s_name) != 0)
  799.       continue;
  800.     if (kill(pid, st->s_signal) < 0)
  801.       log(LOG_LOG, "Couldn't send %s signal to daemon[%d] - is it running?",
  802.       st->s_action, pid);
  803.     else
  804.       log(LOG_LOG, "Sent %s signal to daemon[%d]",st->s_action,pid);
  805.     return(0);
  806.   }
  807.   return(-1);
  808. }
  809.  
  810.  
  811. /* safe enough */
  812. private int
  813. uab_end()
  814. {
  815.   log(LOG_LOG, "Exiting - stopped by remote");
  816.   unlink(uab_pidfile);
  817.   exit(0);
  818. }
  819.  
  820. /* nothing yet */
  821. /* unsafe (defer until later) */
  822. private int
  823. table_dump()
  824. {
  825.   signalactions |= SA_TABLE_DUMP;
  826.   signal(SIG_TDUMP, table_dump);
  827. }
  828.  
  829. private int
  830. stats_dump()
  831. {
  832.   signalactions |= SA_STATISTICS;
  833.   signal(SIG_STAT, stats_dump);
  834. }
  835.  
  836. private int
  837. uab_undebug()
  838. {
  839.   debug = 0;
  840.   signalactions |= SA_UNDEBUG;
  841.   signal(SIG_NODEBUG, uab_undebug);
  842. }
  843.  
  844. private int
  845. uab_debuginc()
  846. {
  847.   signalactions |= SA_DEBUG;
  848.   debug++;
  849.   signal(SIG_DEBUG, uab_debuginc);
  850. }
  851.  
  852. /*
  853.  * run deferred actions
  854.  *
  855.  * returns FALSE if everythings should stop
  856. */
  857. private int
  858. runsignalactions()
  859. {
  860.   int done = 0;            /* init to zero */
  861.  
  862.   while (signalactions) {
  863.     /* always allow undebug and debug to run */
  864.     if ((SA_UNDEBUG & signalactions) && debug == 0) {
  865.       set_debug_level(debug);
  866.       log(LOG_LOG, "DEBUGGING OFF");
  867.       if (uab_runfile) {
  868.     nologfile();
  869.     uab_runfile = NULL;        /* reset this */
  870.       }
  871.       signalactions &= ~SA_UNDEBUG;
  872.     }
  873.     if ((SA_DEBUG & signalactions) && debug != 0) {
  874.       if (!islogfile()) {
  875.     uab_runfile = UAB_RUNFILE;
  876.     logfileis(uab_runfile, "w+");
  877.       }
  878.       set_debug_level(debug);
  879.       log(LOG_LOG, "Debugging level is now %d", debug);
  880.       signalactions &= ~SA_DEBUG;
  881.     }
  882.     /* only run one of these at a time */
  883.     if (SA_TABLE_DUMP & signalactions) {
  884.       FILE *fd;
  885.       long t;
  886.  
  887.       done = SA_TABLE_DUMP;
  888.       if ((fd = fopen(uab_dumpfile, "a+")) == NULL) {
  889.     log(LOG_LOG|L_UERR, "can't open dump file %s", uab_dumpfile);
  890.       } else {
  891.     chmod(uab_dumpfile, 0774);
  892.     time(&t);
  893.     fprintf(fd, "Tables dump at %s", ctime(&t));
  894.     interface_dump_table(fd);
  895.     rtmp_dump_table(fd);
  896.     fclose(fd);
  897.       }
  898.     } else if (SA_STATISTICS & signalactions) {
  899.       FILE *fd;
  900.       long t;
  901.       
  902.       done = SA_STATISTICS;
  903.       if ((fd = fopen(uab_statsfile, "a+")) == NULL) {
  904.     log(LOG_LOG|L_UERR, "can't open statistics file %s", uab_statsfile);
  905.       } else {
  906.     chmod(uab_statsfile, 0774);
  907.     time(&t);
  908.     fprintf(fd, "Statistics dump at %s", ctime(&t));
  909.     ddp_dump_stats(fd);
  910.     rtmp_dump_stats(fd);
  911.     interface_dump_stats(fd);
  912.     fclose(fd);
  913.       }
  914.     }
  915.     signalactions &= ~done;    /* turn off run signals */
  916.   }
  917.   return(TRUE);
  918. }
  919.  
  920.